package service

import (
	baseStore "gitee.com/zaiqiang231/go-base-app/base_app/store"
	"gitee.com/zaiqiang231/zcamp-service-camp/app/model"
	"gitee.com/zaiqiang231/zcamp-service-camp/app/model/req"
	"gorm.io/gorm"
	"sort"
)

type ServiceDistrict struct{}

var ServiceDistrictInstance = new(ServiceDistrict)

func (service *ServiceDistrict) GetTreePartial(request req.DistrictTreeReq) (treeHead *model.DistrictTree, err error) {
	baseStore.GetDataStore().Execute(func(db *gorm.DB) {
		treeHead = &model.DistrictTree{}
		if request.AdCode != "" {
			err = db.Model(model.District{}).Where("ad_code = ?", request.AdCode).Find(&treeHead).Error
			if err != nil {
				return
			}
		}
		err = db.Model(model.District{}).Where("belong_id = ?", treeHead.ID).Order("sort desc, id").Find(&treeHead.Children).Error
		if err != nil {
			return
		}
	})
	return
}

func (service *ServiceDistrict) GetTreeTotal(request req.DistrictTreeReq) (treeHead *model.DistrictTree, err error) {
	baseStore.GetDataStore().Execute(func(db *gorm.DB) {
		var datas = make([]model.District, 0)
		err = db.Model(model.District{}).Find(&datas).Error
		if err != nil {
			return
		}
		var headDistrict model.District
		dataMap := make(map[uint][]model.District)
		for _, v := range datas {
			if request.AdCode == v.AdCode {
				headDistrict = v
			}
			if _, ok := dataMap[v.BelongId]; !ok {
				dataMap[v.BelongId] = make([]model.District, 0)
			}
			dataMap[v.BelongId] = append(dataMap[v.BelongId], v)
		}

		treeHead, err = getDistrictTreeByRecursion(headDistrict, dataMap)
		if err != nil {
			return
		}
	})
	return
}

func getDistrictTreeByRecursion(head model.District, datas map[uint][]model.District) (*model.DistrictTree, error) {
	var result = new(model.DistrictTree)
	result.District = head
	result.Children = make([]*model.DistrictTree, 0)
	var err error
	for _, child := range datas[head.ID] {
		tempHead, temperr := getDistrictTreeByRecursion(child, datas)
		if temperr != nil {
			err = temperr
			return nil, err
		}
		result.Children = append(result.Children, tempHead)
	}
	sort.SliceStable(result.Children, func(i, j int) bool {
		return result.Children[i].Sort > result.Children[j].Sort
	})
	return result, err
}

func (service *ServiceDistrict) GetAdCodeList(requestAdCode string) (resultAdCodeList []string, err error) {
	baseStore.GetDataStore().Execute(func(db *gorm.DB) {
		var datas = make([]model.District, 0)
		err = db.Model(model.District{}).Order("id").Find(&datas).Error
		if err != nil {
			return
		}

		var headDistrict model.District
		dataMap := make(map[uint][]model.District)
		for _, v := range datas {
			if headDistrict.AdCode == "" && requestAdCode == v.AdCode {
				headDistrict = v
			}
			if _, ok := dataMap[v.BelongId]; !ok {
				dataMap[v.BelongId] = make([]model.District, 0)
			}
			dataMap[v.BelongId] = append(dataMap[v.BelongId], v)
		}

		resultAdCodeMap := make(map[string]bool)
		err = getAdCodeListByRecursion(&resultAdCodeList, resultAdCodeMap, headDistrict, dataMap)
		if err != nil {
			return
		}
	})
	return
}

func getAdCodeListByRecursion(adCodeList *[]string, adCodeMap map[string]bool, head model.District, dataMap map[uint][]model.District) error {
	if !adCodeMap[head.AdCode] {
		*adCodeList = append(*adCodeList, head.AdCode)
		adCodeMap[head.AdCode] = true
	}

	subList := dataMap[head.ID]
	sort.SliceStable(subList, func(i, j int) bool {
		return subList[i].Sort > subList[j].Sort
	})
	var err error
	for _, child := range subList {
		if !adCodeMap[child.AdCode] {
			*adCodeList = append(*adCodeList, child.AdCode)
			adCodeMap[child.AdCode] = true
		}
		//只要一级
		//temperr := getAdCodeListByRecursion(adCodeList, adCodeMap, child, dataMap)
		//if temperr != nil {
		//	err = temperr
		//	return err
		//}
	}
	return err
}

func (service *ServiceDistrict) GetProvinceAndCityList() (provinceList []model.District, cityList []model.District, err error) {
	baseStore.GetDataStore().Execute(func(db *gorm.DB) {
		err = db.Model(model.District{}).Where("deep = ?", 0).Order("sort desc, id").Find(&provinceList).Error
		if err != nil {
			return
		}
		err = db.Model(model.District{}).Where("deep = ?", 1).Order("sort desc, id").Find(&cityList).Error
		if err != nil {
			return
		}
	})
	return
}
